using System;
using Slaks.DocumentSerialization;
using Slaks.Graphs.Comparators;

namespace Slaks.Graphs.GraphBuilder
{
	public class SlaksBuilder
	{
		/// <summary>
		/// Removes the rest of infrequent vertices leaving at most (numberOfVerticesToLeave)
		/// </summary>
		/// <param name="numberOfVerticesToLeave"></param>
		public void RemoveInfrequentVertices(Document document,Graph graph, int numberOfVerticesToLeave)
		{
			VertexList vertexList = graph.GetVertexList();
			Id2VertexMap id2VertexMapper = graph.GetId2VertexMap();
			if (numberOfVerticesToLeave <= 0) return;
			int totalCount = vertexList.Count;
			if (numberOfVerticesToLeave >= totalCount) return;
			//what is desired length of the vertex list

			graph.SortVertices(new FrequencyComparer());

			int currentIndex = numberOfVerticesToLeave;

			long idToRemove;
			while (vertexList.Count > numberOfVerticesToLeave)
			{
				idToRemove = vertexList[currentIndex].GetId();
				vertexList.RemoveAt(currentIndex);
				id2VertexMapper.Remove(idToRemove);
			}

			//iterate through existing vertices and eliminate edges to nodes that doesn't exist any more after 
			//infrequent vertices were removed

			long id;
			Vertex target;
			foreach (Vertex vertex in vertexList)
			{
				SectionType2EdgeListMap section2edge = vertex.GetSection2EdgeMap();
				//iterate through edges
				foreach (EdgeList edgeList in section2edge.Values)
				{
					for (int i = 0; i < edgeList.Count; i++)
					{
						target = edgeList[i].GetTarget();
						id = target.GetId();
						if (id2VertexMapper.Contains(id) == false)
						{
							edgeList.RemoveAt(i);
							i--; //if edge is to be removed at place i, then when it is removed, the next edge will be moved at place i, 
							//then we need to decrement i, because next iteration of for will increase it.
						}
					}
				}

				//check if some sectionType now is empty, then remove it.
				string []sectionTypeArray = new string[section2edge.Count];
				section2edge.Keys.CopyTo(sectionTypeArray,0);
				foreach (string sectionType in sectionTypeArray)
				{
					if (section2edge[sectionType].Count == 0) section2edge.Remove(sectionType);
				}
			}
		}
	}
}
